using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Diagnostics;
using Goheer.EXIF;


namespace Pix2Gallery2
{
    static class ImageHandler
    {
        //public bool resizeError;

        /// <summary>
		/// Returns a string that is a filepath to the resized file in a temp directory.
		/// The resized file will be the same name and the same aspect ratio as the original file.
		/// </summary>
		/// <param name="filePath">Path to the original file</param>
		/// <param name="maxWidth">Maximum width for the resized file</param>
        /// <param name="maxHeight">Maximum height for the resized file</param>
        public static string ResizePicture_ConstantAspectRatio(string filePath, int maxWidth, int maxHeight)
        {
            string newPath = "";
            int newWidth;
            int newHeight;

            //this.resizeError = false;

            Bitmap origBmp = new Bitmap(filePath);

            if (origBmp.Width < maxWidth && origBmp.Height < maxHeight)
                return filePath;
            //>> 20070910 SM
            //No resizing
            if ((maxHeight == 0) && (maxWidth == 0))
                return filePath;

            //{
            //    newHeight = origBmp.Height;
            //    newWidth = origBmp.Width;
            //}
            ////<< 20070910 SM
            ////Landscape
            //else if (origBmp.Width > origBmp.Height)
            //{
            //    if (origBmp.Width > maxWidth) newWidth = maxWidth;
            //    else newWidth = origBmp.Width;
            //    newHeight = (int)(newWidth * origBmp.Height / origBmp.Width);
            //    if (newHeight > maxHeight) this.resizeError = true;
            //}
            ////Portrait (or square)
            //else
            //{
            //    if (origBmp.Height > maxWidth) newHeight = maxHeight;
            //    else newHeight = origBmp.Height;
            //    newWidth = (int)(newHeight * origBmp.Width / origBmp.Height);
            //    if (newWidth > maxWidth) this.resizeError = true;
            //}

            //if (this.resizeError)
            //{
            //    Trace.WriteLine("ImageHandler.ResizePicture_ConstantAspectRatio error for " + filePath);
            //    Trace.WriteLine("origWidth = " + origBmp.Width.ToString() + " newWidth = " + newWidth.ToString() + " maxWidth = " + maxWidth.ToString());
            //    Trace.WriteLine("origHeight = " + origBmp.Height.ToString() + " newHeight = " + newHeight.ToString() + " maxHeight = " + maxHeight.ToString());
            //    return filePath;
            //}

            Size newSize = ResizeToFit(origBmp.Width, origBmp.Height, maxWidth, maxHeight);
            newWidth = newSize.Width;
            newHeight = newSize.Height;
            
            newPath = Path.GetTempPath() + @"Pix2Gallery2\";
            Directory.CreateDirectory(newPath);
            newPath = newPath + Path.GetFileName(filePath); 

            Bitmap convBmp = new Bitmap(newWidth, newHeight);
            Graphics g = Graphics.FromImage(convBmp);
            //>> 20070910 SM
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
            //>> 20070910 SM
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            g.FillRectangle(Brushes.White, 0, 0, newWidth, newHeight);
            g.DrawImage(origBmp, 0, 0, newWidth, newHeight);

            //Copy the EXIF information from the original to the newly resized image
            Trace.WriteLine(">> Writing EXIF information to resized file");
            EXIFextractor convEXIF = new EXIFextractor(ref convBmp, "");

            //This copies the raw properties to the converted file - provides a more exact copy
            foreach (PropertyItem p in origBmp.PropertyItems)
            {
                if(p.Value != null)
                    convEXIF.setTag(p.Id, p.Len, p.Type, p.Value);
            }

            //<< 20070910 SM
            convBmp.Save(newPath, ImageFormat.Jpeg);
            //<< 20070910 SM

            origBmp.Dispose();

            return newPath;
        }

        /// <summary> 
        /// Calculates new image size by scaling original to fit into the given boundary.
        /// </summary>
        /// <param name="originalWidth">Original image width</param>
        /// <param name="originalHeight">Original image height</param>
        /// <param name="boundaryWidth">Boundary width</param>
        /// <param name="boundaryHeight">Boundary height</param>
        /// <returns>Resized image size</returns>
        public static Size ResizeToFit(int originalWidth, int originalHeight, int boundaryWidth, int boundaryHeight)
        {
            return ResizeToFit(new Size(originalWidth, originalHeight), new Size(boundaryWidth, boundaryHeight));
        }

        /// <summary>
        /// Calculates new image size by scaling original to fit into the given boundary.
        /// </summary>
        /// <param name="original">Original image size</param>
        /// <param name="boundary">Boundary size</param>
        /// <returns>Resized image size</returns>
        public static Size ResizeToFit(Size original, Size boundary)
        {
            SizeF originalF = new SizeF(original);
            SizeF boundaryF = new SizeF(boundary);
            float widthRatio = boundaryF.Width / originalF.Width;
            float heightRatio = boundaryF.Height / originalF.Height;

            if (widthRatio == heightRatio) // 1:1 aspect ratio
                return boundaryF.ToSize();
            else if (widthRatio < heightRatio) // adjust by boundary width
                return new SizeF(boundaryF.Width, originalF.Height * widthRatio).ToSize();
            else // adjust by boundary height
                return new SizeF(originalF.Width * heightRatio, boundaryF.Height).ToSize();
        }

        /// <summary>
        /// <summary>
        /// Returns an image that has been cropped and scaled to thumbSize.
        /// The resized image will always be a cropped square from the middle of the image.
        /// </summary>
        /// <param name="filePath">Path to the original file</param>
        /// <param name="thumbSize">Size for the resized image</param>
        public static Image GetSquareThumbnail(string filePath, int thumbSize)
        {
            //string newPath = "";
            //int newWidth;
            //int newHeight;
            Rectangle srcRect;

            //this.resizeError = false;

            Image origImg = new Bitmap(filePath);

            if (origImg.Width < thumbSize && origImg.Height < thumbSize)
                return origImg;

            Rectangle destRec = new Rectangle(0, 0, thumbSize, thumbSize);

            //Landscape
            if (origImg.Width > origImg.Height)
            {
                int x = (int)(origImg.Width - origImg.Height)/2;
                srcRect = new Rectangle(x, 0, origImg.Height, origImg.Height);
            }
            //Portrait (or square)
            else
            {
                int y;
                if (origImg.Width == origImg.Height) y = 0;
                else y = (int)(origImg.Height - origImg.Width) / 2;
                srcRect = new Rectangle(0, y, origImg.Width, origImg.Width);
            }

            //newPath = Path.GetTempPath() + @"Pix2Gallery2\";
            //Directory.CreateDirectory(newPath);
            //newPath = newPath + Path.GetFileName(filePath); 

            Image thumbImg = new Bitmap(thumbSize, thumbSize);
            Graphics g = Graphics.FromImage(thumbImg);
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            g.FillRectangle(Brushes.White, 0, 0, thumbSize, thumbSize);
            g.DrawImage(origImg, destRec, srcRect, GraphicsUnit.Pixel);
            
            //thumbImg.Save(newPath);

            return thumbImg;
        }
    }
}
